Completed
Push — master ( 8b46e7...297444 )
by Andres
28s
created

angular.controller(ꞌct_redoxꞌ)   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 5
c 2
b 0
f 1
nc 8
dl 0
loc 27
rs 8.439
nop 2
1
/**
2
 redox
3
 Component that handles reduction/oxidation and ions.
4
5
 @namespace Components
6
 */
7
'use strict';
8
9
angular.module('game').component('redox', {
10
  templateUrl: 'views/redox.html',
11
  controller: 'ct_redox',
12
  controllerAs: 'ct'
13
});
14
15
angular.module('game').controller('ct_redox', ['state', 'data', 'visibility', 'util', 'format', 'reaction',
16
  function (state, data, visibility, util, format, reaction) {
17
    let ct = this;
18
    ct.state = state;
19
    ct.data = data;
20
    ct.util = util;
21
    ct.format = format;
22
    ct.reaction = reaction;
23
24
    function update(player) {
25
      processRedox(player);
26
      processElectronegativity(player);
27
    }
28
29
    function processRedox(player){
30
      for(let slot of player.element_slots){
31
        if(!slot){
32
          continue;
33
        }
34
        for (let redox of slot.redoxes) {
35
          if (!redox.resource || !redox.active) {
36
            continue;
37
          }
38
39
          let reactant = ct.generateName(redox.element, redox.from);
40
          let power = ct.redoxPower(player);
41
          let number = Math.min(power, player.resources[reactant].number);
42
          let react = ct.redoxReaction(redox);
43
44
          ct.reaction.react(number, react, player);
45
        }
46
      }
47
    }
48
49
    function processElectronegativity(player){
50
      for(let key in data.elements){
51
        let element = data.elements[key];
52
        if(element.electronegativity === 0){
53
          continue;
54
        }
55
        let ions = element.anions.concat(element.cations);
56
		    ions.push(element.main);
57
        for(let resource of ions){
58
          if(player.resources[resource].number === 0){
59
            continue;
60
          }
61
          let charge = data.resources[resource].charge || 0;
62
          let probabilities = probabilityDistribution(key, charge);
63
          for(let probKey in probabilities){
64
            if(probKey === charge){
65
              continue;
66
            }
67
            let production = Math.floor(probabilities[probKey]*player.resources[resource].number);
68
            if(production === 0){
69
              continue;
70
            }
71
            let react = ct.redoxReaction({
72
              element: key,
73
              from: charge,
74
              to: parseInt(probKey, 10)
75
            });
76
            // electronegativity is 'for free'
77
      			react.reactant.eV = 0;
78
            // FIXME: starvation should fix this
79
            if(react.reactant['e-']){
80
              production = Math.min(production, player.resources['e-'].number);
81
            }
82
            ct.reaction.react(production, react, player);
83
          }
84
        }
85
      }
86
    }
87
88
    function probabilityDistribution(element, charge){
89
    	let prob = {};
90
    	let start = -data.elements[element].electron_affinity.length;
91
    	let end = charge;
92
    	// lower than index, affected by negativity
93
    	rangeProbability(element, prob, start, end, 1, data.elements[element].negative_factor);
94
95
    	prob[charge] = 1;
96
      // Huh, special case... we don't want e- and p gone too fast :(
97
      if(element === 'H' && charge === 1){
98
        prob[charge] = 5e5;
99
      }
100
101
    	start = charge+1;
102
    	end = data.elements[element].ionization_energy.length+1;
103
    	// lower than index, affected by positivity
104
    	rangeProbability(element, prob, start, end, -1, data.elements[element].positive_factor);
105
106
    	let sum = 0;
107
    	for(let i in prob){
108
    		sum += prob[i];
109
    	}
110
    	for(let i in prob){
111
    		prob[i] /= sum;
112
    	}
113
    	return prob;
114
    }
115
116
    function rangeProbability(element, prob, start, end, offset, factor){
117
    	for(let i = start; i < end; i++){
118
    		let difference = data.redox[element][i]-data.redox[element][i+offset];
119
    		if(difference <= 0){
120
    			difference = -difference;
121
    		}else{
122
    			difference = 1/difference;
123
    		}
124
    		prob[i] = Math.pow(data.constants.ELECTRONEGATIVITY_CHANCE,Math.abs(i))*factor*difference;
125
    	}
126
    }
127
128
    /* Calculates the redox power based on the redox upgrades */
129
    ct.redoxPower = function(player) {
130
      let level = player.global_upgrades.redox_bandwidth;
131
      let upgrade = data.global_upgrades.redox_bandwidth;
132
      let basePower = upgrade.power;
133
      let polynomial = upgrade.power_poly;
134
      return basePower * Math.floor(Math.pow(level, polynomial));
135
    };
136
137
    /* Writes a redox in the form of a reaction so that we can use the reaction
138
    service to process it */
139
    ct.redoxReaction = function (redox) {
140
      let reactant = ct.generateName(redox.element, redox.from);
141
      let product = ct.generateName(redox.element, redox.to);
142
      let energy = redoxEnergy(redox.from, redox.to, redox.element);
143
144
      let react = {
145
        'reactant': {},
146
        'product': {}
147
      };
148
149
      react.reactant[reactant] = 1;
150
      react.product[product] = 1;
151
      if (energy > 0) {
152
        react.reactant.eV = energy;
153
      } else if (energy < 0) {
154
        react.product.eV = -energy;
155
      }
156
157
      let electron = redox.from - redox.to;
158
      if (electron > 0) {
159
        react.reactant['e-'] = electron;
160
      } else if (electron < 0) {
161
        react.product['e-'] = -electron;
162
      }
163
164
      return react;
165
    };
166
167
    /* Calculates how much energy it takes to go from a redox level to another
168
    for a given element */
169
    function redoxEnergy(from, to, element) {
170
      let energyFrom = data.redox[element][from];
171
      let energyTo = data.redox[element][to];
172
      let energy = energyTo - energyFrom;
173
174
      return energy;
175
    }
176
177
    /* Generates the name of a ion, e.g. O3+ */
178
    ct.generateName = function (element, i) {
179
      if (i === 0) {
180
        return data.elements[element].main;
181
      }
182
      let postfix = '';
183
      if (Math.abs(i) > 1) {
184
        postfix = Math.abs(i);
185
      }
186
      postfix += getSign(i);
187
      let name = element + postfix;
188
      // special case!! H+ is just a proton
189
      if (name === 'H+') {
190
        name = 'p';
191
      }
192
      return name;
193
    };
194
195
    function getSign(number) {
196
      return number > 0 ? '+' : '-';
197
    }
198
199
    /* Calculates the number of redox slots based on the redox upgrades */
200
    ct.redoxSlots = function (player) {
201
      let level = player.global_upgrades.redox_slots;
202
      let upgrade = data.global_upgrades.redox_slots;
203
      let basePower = upgrade.power;
204
      let multiplier = upgrade.power_mult;
205
      return basePower * Math.floor(multiplier * level);
206
    };
207
208
    ct.redoxSize = function (player) {
209
      let size = 0;
210
      for(let slot of player.element_slots){
211
        if(!slot){
212
          continue;
213
        }
214
        size += slot.redoxes.length;
215
      }
216
      return size;
217
    };
218
219
    /* Adds a new redox to the player list */
220
    ct.addRedox = function (player, slot) {
221
      if(ct.redoxSize(player) >= ct.redoxSlots(player)){
222
        return;
223
      }
224
      slot.redoxes.push({
225
        resource: data.elements[slot.element].main,
226
        active: false,
227
        element: slot.element,
228
        from: 0,
229
        to: 1
230
      });
231
    };
232
233
    ct.removeRedox = function (slot, index) {
234
      slot.redoxes.splice(index, 1);
235
    };
236
237
    ct.visibleRedox = function(slot) {
238
      return slot.redoxes;
239
    };
240
241
    state.registerUpdate('redox', update);
242
  }
243
]);
244